#pragma once

#include "List.h"
#include "ListDataTypes.h"
#include "ListDetails.h"
#include "SearchKbd.h"
#include "GrpPos.h"

class CListBase : public CList
{
public:
  CListBase(HWND hParent);
  virtual ~CListBase();

  virtual void Clear();

  virtual bool OnMouseDown(int x, int y);
  virtual bool OnMouseMove(int x, int y);

  virtual bool OnKeyDown(int vKey, bool bRepeating);

  virtual void SelectPrev();
  virtual void SelectNext();

  virtual const RECT& GetRect() const
  { return fullRect; }
  virtual void SetRect(const RECT& rc);

  virtual void Redraw()
  { ::InvalidateRect(parentWnd, &fullRect, FALSE); }

  virtual void Draw(HDC hdc, HDC hdcTmp, const RECT& rClip);
  virtual void DrawOverlays(HDC hdc, HDC hdcTmp, const RECT& rClip);

  virtual bool ReloadItem(CEOID oid)
  { return false; }

  virtual void CalculateHeights();

  void SetExtraHeight(int extraHeight = 0)
  { extraScrollHeight = extraHeight; }

  const CGrpPos& GetGroupPos() const
  { return groupPos; }

  int  GetItemIdxByOid(CEOID oid) const;

  CListItemBase* GetItem(int idx)
  { if (idx < 0 || idx >= (int)items.size()) return NULL;
    else return (CListItemBase*)items[idx]; }
  const CListItemBase* GetItem(int idx) const
  { if (idx < 0 || idx >= (int)items.size()) return NULL;
    else return (const CListItemBase*)items[idx]; }
  CListItemBase* GetSelectedItem()
  { return GetItem(selection); }
  const CListItemBase* GetSelectedItem() const
  { return GetItem(selection); }

  bool IsFiltered() const
  { return isFiltered; }
  bool IsItemNewGroup(int index) const;
  bool IsShowGroupHeaders() const
  { return showGroupHeaders; }

  void SelectItemByGroup(int groupIdx);

  //
  // Search Engine
  //
  void ApplyFilter(const SearchKbdKeys* filter, int len, TCHAR match[], bool redraw = true);
  void ApplyFilter(const TCHAR* filter, bool redraw = true);
  void ClearFilter();
  int  FilterIdxToListIdx(int idx);
  int  ListIdxToFilterIdx(int idx);

  // Scroll
  void ScrollBar(int y);
  virtual void ScrollTo(int pos, int time);
  virtual void StopScrolling();
  
  // Header
  const TCHAR* GetHeaderText() const
  { return headerText; }
  void SetHeaderText(const TCHAR* szText);
  void ClearHeaderText();

protected:
  virtual void DrawHeader(HDC hdc, HDC hdcTmp, const RECT& rClip);

  void DrawGroupHeader(HDC hdc, const RECT& rClip);
  void DrawScrollBar(HDC hdc, const RECT& rClip);
  void DrawScrollInd(HDC hdc, const RECT& rClip);

  CListItemBase* BaseItem(int idx)
  { return (CListItemBase*)items[idx]; }
  const CListItemBase* BaseItem(int idx) const
  { return (const CListItemBase*)items[idx]; }

protected:
  CGrpPos          groupPos;
  bool             showGroupHeaders;
  TCHAR            listIndOverride;

  RECT  fullRect;
  int   headerHeight;

  TCHAR headerText[HEADER_TEXT_LENGTH];
  int   headerTextLen;

  int   extraScrollHeight;

  // Search Engine
  bool              isFiltered;
  CList::CListItems allItems;
};